from rest_framework import viewsets, status
from rest_framework.decorators import action, api_view, permission_classes
from rest_framework.response import Response
from rest_framework.permissions import IsAuthenticated, AllowAny
from django.utils import timezone
from datetime import datetime, timedelta, date
import re
import logging
from ..services.ai_services import ScheduleAIService


logger = logging.getLogger('apps')


class BaseResponse:
    """基础响应类"""

    @staticmethod
    def success(data=None, message="操作成功"):
        return Response({
            "status": "success",
            "message": message,
            "data": data
        })

    @staticmethod
    def error(message="操作失败", status=status.HTTP_400_BAD_REQUEST):
        return Response({
            "status": "error",
            "message": message
        }, status=status)


@api_view(['POST'])
@permission_classes([IsAuthenticated])
def process_schedule_draft(request):
    """处理日程草稿"""
    try:
        draft_text = request.data.get('draft_text')
        if not draft_text:
            return BaseResponse.error("日程内容不能为空")

        # 获取目标日期
        target_date = request.data.get('target_date')
        if target_date:
            try:
                target_date = datetime.strptime(target_date, '%Y-%m-%d').date()
            except ValueError:
                return BaseResponse.error("日期格式错误，请使用 YYYY-MM-DD 格式")
        else:
            target_date = timezone.now().date()

        # 后端自己生成当前日期信息，不依赖前端传递
        now = timezone.now()
        current_date = now.date()
        current_date_info = {
            'year': current_date.year,
            'month': current_date.month,
            'day': current_date.day,
            'weekday': current_date.weekday()  # Python格式：0=周一,6=周日
        }

        # 记录日期信息
        logger.info(f"后端生成的当前日期信息: {current_date_info}")
        logger.info(f"目标日期: {target_date}")
        logger.info(f"处理日程草稿: {draft_text}")

        # 创建服务实例
        service = ScheduleAIService()

        # 分析内容，传递当前日期信息
        schedules = service.analyze_content(draft_text, current_date_info)

        # 如果分析失败，创建一个基本的日程信息
        if not schedules:
            logger.warning("AI分析失败，使用基本规则创建日程")
            # 创建一个基本的日程信息
            basic_schedule = {
                'title': draft_text[:30] if len(draft_text) > 30 else draft_text,
                'description': draft_text,
                'date': target_date.strftime('%Y-%m-%d'),
                'start_time': '09:00',
                'end_time': '10:00',
                'period': 'morning',
                'importance': 'medium',
                'status': 'pending',
                'reminder': True,
                'reminder_time': None,
                'location': '',
                'key_points': [],
                'is_date_ai_suggested': True,
                'is_time_ai_suggested': True
            }
            schedules = [basic_schedule]

        # 处理前端传递的多事件数据
        events_data = request.data.get('events', [])
        if events_data and isinstance(events_data, list) and len(events_data) > 0:
            logger.info(f"前端传递了 {len(events_data)} 个事件数据，进行处理")

            # 创建新的日程列表
            new_schedules = []

            for event in events_data:
                # 获取原始文本和日期表达式
                original_text = event.get('original_text', '')
                date_expressions = event.get('date_expressions', [])

                if original_text:
                    logger.info(f"处理事件原始文本: {original_text}")
                    if date_expressions:
                        logger.info(f"日期表达式: {date_expressions}")

                    # 使用原始文本重新提取日期
                    extracted_date = None

                    # 如果有日期表达式，优先处理
                    if date_expressions and isinstance(date_expressions, list):
                        for expr in date_expressions:
                            # 尝试从每个日期表达式中提取日期
                            temp_date = service._extract_date_info(expr, current_date)
                            if temp_date:
                                extracted_date = temp_date
                                logger.info(f"从日期表达式 '{expr}' 提取到日期: {extracted_date}")
                                break

                    # 如果没有从日期表达式中提取到日期，尝试从原始文本中提取
                    if not extracted_date:
                        extracted_date = service._extract_date_info(original_text, current_date)
                        if extracted_date:
                            logger.info(f"从原始文本中提取到日期: {extracted_date}")

                    # 如果提取到了日期，更新事件的日期
                    if extracted_date:
                        event['date'] = extracted_date.strftime('%Y-%m-%d')
                        event['is_date_ai_suggested'] = True
                    else:
                        # 如果没有提取到日期，使用目标日期
                        event['date'] = target_date.strftime('%Y-%m-%d')
                        event['is_date_ai_suggested'] = True
                        logger.info(f"未能提取到日期，使用目标日期: {target_date}")

                # 添加到新的日程列表
                new_schedules.append(event)

            # 如果成功处理了前端传递的事件数据，使用新的日程列表
            if new_schedules:
                schedules = new_schedules
                logger.info(f"使用前端传递的事件数据，共 {len(schedules)} 个事件")

        # 确保所有日期使用正确的年份
        current_year = timezone.now().year
        for schedule in schedules:
            if 'date' in schedule and schedule['date']:
                try:
                    # 解析日期
                    date_obj = datetime.strptime(schedule['date'], '%Y-%m-%d').date()

                    # 记录原始日期，用于日志
                    original_date = date_obj

                    # 检查日期是否合理
                    # 1. 如果年份不是当前年份，可能需要调整
                    if date_obj.year != current_year:
                        # 创建新的日期对象，保持月和日不变，但使用当前年份
                        new_date = date_obj.replace(year=current_year)

                        # 检查日期是否已过
                        if new_date < current_date:
                            # 如果是相对日期（如"下周X"），且日期已过，可能需要使用正确的日期
                            # 通过计算与当前日期的差距来判断是否为相对日期
                            days_diff = abs(
                                (date_obj - datetime.strptime(date_obj.strftime("%Y-01-01"), "%Y-%m-%d").date()).days -
                                (current_date - datetime.strptime(str(current_year) + "-01-01",
                                                                  "%Y-%m-%d").date()).days)

                            # 如果差距小于30天，可能是相对日期
                            if days_diff < 30:
                                # 保持原有月日，只修改年份
                                new_date = date_obj.replace(year=current_year)
                                logger.info(f"检测到可能的相对日期: {date_obj}，保留原日期")
                            else:
                                # 检查是否是月份问题
                                # 例如，现在是12月，用户说"1月15日"，应该是指明年1月
                                if date_obj.month < current_date.month:
                                    # 月份小于当前月份，可能是指明年
                                    new_date = date_obj.replace(year=current_year + 1)
                                    logger.info(f"检测到可能的明年日期: {date_obj}，修正为: {new_date}")
                                else:
                                    # 可能是明年的日期
                                    new_date = new_date.replace(year=current_year + 1)
                                    logger.info(f"日期已过，使用明年的日期: {new_date}")

                        date_obj = new_date

                    # 2. 即使年份是当前年份，也需要检查日期是否已过
                    elif date_obj < current_date:
                        # 检查是否是近期日期（30天内）
                        days_diff = (current_date - date_obj).days
                        if days_diff <= 30:
                            # 如果是本月的日期但已过，可能是指下个月
                            if date_obj.month == current_date.month:
                                # 尝试使用下个月
                                next_month = current_date.month + 1
                                next_year = current_year
                                if next_month > 12:
                                    next_month = 1
                                    next_year += 1

                                try:
                                    new_date = date(next_year, next_month, date_obj.day)
                                    logger.info(f"日期已过 ({date_obj})，尝试使用下个月: {new_date}")
                                    date_obj = new_date
                                except ValueError:
                                    # 处理无效日期（如2月30日）
                                    logger.warning(f"下个月的日期无效: {next_year}-{next_month}-{date_obj.day}")
                                    # 使用下个月的最后一天
                                    if next_month == 2:
                                        # 处理闰年
                                        if (next_year % 4 == 0 and next_year % 100 != 0) or (next_year % 400 == 0):
                                            last_day = 29
                                        else:
                                            last_day = 28
                                    elif next_month in [4, 6, 9, 11]:
                                        last_day = 30
                                    else:
                                        last_day = 31

                                    new_date = date(next_year, next_month, last_day)
                                    logger.info(f"使用下个月的最后一天: {new_date}")
                                    date_obj = new_date
                            # 如果是上个月的日期，可能是指下个月
                            elif date_obj.month == current_date.month - 1 or (
                                    current_date.month == 1 and date_obj.month == 12):
                                # 尝试使用下个月
                                next_month = current_date.month + 1
                                next_year = current_year
                                if next_month > 12:
                                    next_month = 1
                                    next_year += 1

                                try:
                                    new_date = date(next_year, next_month, date_obj.day)
                                    logger.info(f"日期是上个月 ({date_obj})，尝试使用下个月: {new_date}")
                                    date_obj = new_date
                                except ValueError:
                                    # 处理无效日期
                                    logger.warning(f"下个月的日期无效: {next_year}-{next_month}-{date_obj.day}")
                                    # 使用当前日期
                                    date_obj = current_date
                                    logger.info(f"使用当前日期: {date_obj}")
                        else:
                            # 日期差距较大，可能是用户确实想要设置过去的日期
                            # 或者是日期提取错误，此时使用当前日期
                            logger.warning(f"日期 {date_obj} 与当前日期相差 {days_diff} 天，使用当前日期")
                            date_obj = current_date

                    # 如果日期有变化，更新日程中的日期
                    if date_obj != original_date:
                        schedule['date'] = date_obj.strftime('%Y-%m-%d')
                        logger.info(f"更新日期: 从 {original_date} 到 {date_obj}")
                        schedule['is_date_ai_suggested'] = True

                except Exception as e:
                    logger.error(f"处理日期时出错: {str(e)}")
                    # 如果日期格式错误，使用目标日期
                    schedule['date'] = target_date.strftime('%Y-%m-%d')
                    schedule['is_date_ai_suggested'] = True
            else:
                # 如果没有日期，使用目标日期
                schedule['date'] = target_date.strftime('%Y-%m-%d')
                schedule['is_date_ai_suggested'] = True

        # 格式化返回数据，确保所有字段都有有效值
        result = {
            'events': [],
            'count': len(schedules)
        }

        for schedule in schedules:
            # 确保时间格式正确
            start_time = schedule.get('start_time', '09:00')
            end_time = schedule.get('end_time', '10:00')

            # 验证时间格式
            try:
                # 尝试解析时间，确保格式为HH:MM
                if start_time and not re.match(r'^\d{2}:\d{2}$', start_time):
                    logger.warning(f"开始时间格式不正确: {start_time}，使用默认值")
                    start_time = '09:00'

                if end_time and not re.match(r'^\d{2}:\d{2}$', end_time):
                    logger.warning(f"结束时间格式不正确: {end_time}，使用默认值")
                    end_time = '10:00'
            except Exception as e:
                logger.error(f"验证时间格式失败: {str(e)}")
                start_time = '09:00'
                end_time = '10:00'

            # 确保标题不超过50个字符
            title = schedule.get('title', '未命名日程')
            if len(title) > 50:
                title = title[:50]

            # 确保描述字段使用关键点信息
            key_points = schedule.get('key_points', [])
            description = schedule.get('description', '')

            # 如果有关键点，直接使用关键点作为描述
            if key_points and len(key_points) > 0:
                # 使用中文顿号连接关键点
                description = '、'.join(key_points)

                # 确保不超过30个字符
                if len(description) > 30:
                    description = description[:27] + '...'
            elif not description and title:
                # 如果没有关键点和描述，使用标题
                description = title
            else:
                # 如果有描述但没有关键点，移除可能的备注和时间信息
                description_parts = description.split('(备注:')
                if len(description_parts) > 1:
                    description = description_parts[0].strip()

                # 移除时间信息
                description = re.sub(r'(\d{1,2})[点:：时](\d{1,2})?分?', '', description)
                description = re.sub(r'[早中下晚]上|上午|下午|凌晨|傍晚|晚上|早晨', '', description)

                # 确保中文顿号
                description = description.replace(',', '、')
                if '、' not in description and ' ' in description:
                    description = description.replace(' ', '、')

                # 确保简洁性
                description = description.strip()
                if not description:
                    description = "无提醒事项"
                elif len(description) > 30:
                    description = description[:27] + '...'

            event = {
                'title': title,
                'description': description,
                'date': schedule.get('date', target_date.strftime('%Y-%m-%d')),
                'start_time': start_time,
                'end_time': end_time,
                'period': schedule.get('period', 'morning'),
                'importance': schedule.get('importance', 'medium'),
                'location': schedule.get('location', ''),
                'key_points': schedule.get('key_points', []),
                'is_date_ai_suggested': schedule.get('is_date_ai_suggested', False),
                'is_time_ai_suggested': schedule.get('is_time_ai_suggested', False),
                'is_location_ai_suggested': schedule.get('is_location_ai_suggested', False)
            }
            result['events'].append(event)

        # 记录识别结果
        logger.info(f"成功识别 {len(result['events'])} 个日程")
        for i, event in enumerate(result['events']):
            logger.info(
                f"日程 {i + 1}: {event['title']}, 日期: {event['date']}, 时间: {event['start_time']}-{event['end_time']}")

        return BaseResponse.success(result)

    except Exception as e:
        logger.error(f"处理日程草稿失败: {str(e)}")
        # 即使出错，也尝试返回一个基本的日程信息
        try:
            # 确保返回的是有效的JSON格式
            current_date = target_date.strftime('%Y-%m-%d') if target_date else timezone.now().date().strftime(
                '%Y-%m-%d')
            title = draft_text[:30] if draft_text and len(draft_text) > 30 else (draft_text or '未命名日程')

            basic_result = {
                'events': [{
                    'title': title,
                    'description': draft_text or '',
                    'date': current_date,
                    'start_time': '09:00',
                    'end_time': '10:00',
                    'period': 'morning',
                    'importance': 'medium',
                    'location': '',
                    'key_points': [],
                    'is_date_ai_suggested': True,
                    'is_time_ai_suggested': True,
                    'is_location_ai_suggested': False
                }],
                'count': 1
            }

            return BaseResponse.success(basic_result)
        except:
            return BaseResponse.error(f"处理日程草稿失败: {str(e)}")